home *** CD-ROM | disk | FTP | other *** search
- /* SPIM S20 MIPS simulator.
- Macros for accessing memory.
- Copyright (C) 1990 by James Larus (larus@cs.wisc.edu).
-
- SPIM is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 1, or (at your option) any
- later version.
-
- SPIM is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNU CC; see the file COPYING. If not, write to James R.
- Larus, Computer Sciences Department, University of Wisconsin--Madison,
- 1210 West Dayton Street, Madison, WI 53706, USA or to the Free
- Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- A note on directions: "Bottom" of memory is the direction of
- decreasing addresses. "Top" is the direction of increasing addresses.
-
- $Header: /var/home/cs354/.spim/RCS/mem.h,v 1.2 1992/10/07 04:08:04 cs354 Exp $
- */
-
- #ifdef MEM_MAIN
- #define EXTERN
- #else
- #define EXTERN extern
- #endif
-
- /* Type of contents of a memory word. */
-
- typedef long mem_word;
-
-
- /* The text segment and boundaries. */
-
- EXTERN instruction **text_seg;
-
- EXTERN int text_modified; /* Non-zero means text segment was written */
-
- #define TEXT_BOT ((mem_addr) 0x400000)
-
- EXTERN mem_addr text_top;
-
-
- /* Amount to grow text segment when we run out of space for instructions. */
-
- #define TEXT_CHUNK_SIZE 4096
-
-
- /* The data segment and boundaries. */
-
- EXTERN mem_word *data_seg;
-
- EXTERN int data_modified; /* Non-zero means a data segment was written */
-
- EXTERN short *data_seg_h; /* Points to same vector as DATA_SEG */
-
- #ifdef ibm032
- #define BYTE_TYPE signed char
- #else
- #define BYTE_TYPE char
- #endif
-
- EXTERN BYTE_TYPE *data_seg_b; /* Ditto */
-
- #define DATA_BOT ((mem_addr) 0x10000000)
-
- EXTERN mem_addr data_top;
-
- EXTERN mem_addr gp_midpoint; /* Middle of $gp area */
-
-
- /* The stack segment and boundaries. */
-
- EXTERN mem_word *stack_seg;
-
- EXTERN short *stack_seg_h; /* Points to same vector as STACK_SEG */
-
- EXTERN BYTE_TYPE *stack_seg_b; /* Ditto */
-
- EXTERN mem_addr stack_bot;
-
- /* Exclusive, but include 4K at top of stack. */
-
- #define STACK_TOP ((mem_addr) 0x80000000)
-
-
- /* The kernel text segment and boundaries. */
-
- EXTERN instruction **k_text_seg;
-
- #define K_TEXT_BOT ((mem_addr) 0x80000000)
-
- EXTERN mem_addr k_text_top;
-
-
- /* Kernel data segment and boundaries. */
-
- EXTERN mem_word *k_data_seg;
-
- EXTERN short *k_data_seg_h;
-
- EXTERN BYTE_TYPE *k_data_seg_b;
-
- #define K_DATA_BOT ((mem_addr) 0x90000000)
-
- EXTERN mem_addr k_data_top;
-
-
-
- instruction *funny_text_read ();
- void funny_text_write ();
- mem_word bad_mem_read ();
- void bad_mem_write ();
-
-
- /* You would think that a compiler could perform CSE on the arguments to
- these macros. However, complex expressions break some compilers, so
- do the CSE ourselves. */
-
- /* Translate from SPIM memory address to physical address */
-
- #ifdef MACINTOSH
-
- extern mem_addr MEM_ADDRESS(mem_addr addr);
-
- #else
-
- #define MEM_ADDRESS(ADDR) \
- (((mem_addr) (ADDR) >= TEXT_BOT && (mem_addr) (ADDR) < text_top) \
- ? (mem_addr) (ADDR) - TEXT_BOT + (mem_addr) text_seg \
- : (((mem_addr) (ADDR) >= DATA_BOT && (mem_addr) (ADDR) < data_top) \
- ? (mem_addr) (ADDR) - DATA_BOT + (mem_addr) data_seg \
- : (((mem_addr) (ADDR) >= stack_bot && (mem_addr) (ADDR) < STACK_TOP) \
- ? (mem_addr) (ADDR) - stack_bot + (mem_addr) stack_seg \
- : ((mem_addr) (ADDR) >= K_TEXT_BOT && (mem_addr) (ADDR) < k_text_top)\
- ? (mem_addr) (ADDR) - K_TEXT_BOT + (mem_addr) k_text_seg \
- : (((mem_addr) (ADDR) >= K_DATA_BOT && (mem_addr) (ADDR) < k_data_top)\
- ? (mem_addr) (ADDR) - K_DATA_BOT + (mem_addr) k_data_seg \
- : run_error ("Memory address out of bounds\n")))))
-
- #endif
-
- #define SET_MEM_INST(ADDR, INST) \
- {register mem_addr _addr_ = (mem_addr) (ADDR); \
- text_modified = 1; \
- if (_addr_ >= TEXT_BOT && _addr_ < text_top && !(_addr_ & 0x3)) \
- text_seg [(_addr_ - TEXT_BOT) >> 2] = INST; \
- else if (_addr_ >= K_TEXT_BOT && _addr_ < k_text_top && !(_addr_ & 0x3))\
- k_text_seg [(_addr_ - K_TEXT_BOT) >> 2] = INST; \
- else funny_text_write (_addr_, INST);}
-
-
- #define SET_MEM_BYTE(ADDR, VALUE) \
- {register mem_addr _addr_ = (mem_addr) (ADDR); \
- data_modified = 1; \
- if (_addr_ >= DATA_BOT && _addr_ < data_top) \
- data_seg_b [_addr_ - DATA_BOT] = (unsigned char) (VALUE); \
- else if (_addr_ >= stack_bot && _addr_ < STACK_TOP) \
- stack_seg_b [_addr_ - stack_bot] = (unsigned char) (VALUE); \
- else if (_addr_ >= K_DATA_BOT && _addr_ < k_data_top) \
- k_data_seg_b [_addr_ - K_DATA_BOT] = (unsigned char) (VALUE); \
- else bad_mem_write (_addr_, VALUE, 0);}
-
-
- #define SET_MEM_HALF(ADDR, VALUE) \
- {register mem_addr _addr_ = (mem_addr) (ADDR); \
- data_modified = 1; \
- if (_addr_ >= DATA_BOT && _addr_ < data_top && !(_addr_ & 0x1)) \
- data_seg_h [(_addr_ - DATA_BOT) >> 1] = (unsigned short) (VALUE); \
- else if (_addr_ >= stack_bot && _addr_ < STACK_TOP && !(_addr_ & 0x1)) \
- stack_seg_h [(_addr_ - stack_bot) >> 1] = (unsigned short) (VALUE); \
- else if (_addr_ >= K_DATA_BOT && _addr_ < k_data_top && !(_addr_ & 0x1))\
- k_data_seg_h [(_addr_ - K_DATA_BOT) >> 1] = (unsigned short) (VALUE); \
- else bad_mem_write (_addr_, VALUE, 0x1);}
-
-
- #define SET_MEM_WORD(ADDR, VALUE) \
- {register mem_addr _addr_ = (mem_addr) (ADDR); \
- data_modified = 1; \
- if (_addr_ >= DATA_BOT && _addr_ < data_top && !(_addr_ & 0x3)) \
- data_seg [(_addr_ - DATA_BOT) >> 2] = (mem_word) (VALUE); \
- else if (_addr_ >= stack_bot && _addr_ < STACK_TOP && !(_addr_ & 0x3)) \
- stack_seg [(_addr_ - stack_bot) >> 2] = (mem_word) (VALUE); \
- else if (_addr_ >= K_DATA_BOT && _addr_ < k_data_top && !(_addr_ & 0x3))\
- k_data_seg [(_addr_ - K_DATA_BOT) >> 2] = (mem_word) (VALUE); \
- else bad_mem_write (_addr_, VALUE, 0x3);}
-
- #define READ_MEM_INST(LOC, ADDR) \
- {register mem_addr _addr_ = (mem_addr) (ADDR); \
- if (_addr_ >= TEXT_BOT && _addr_ < text_top && !(_addr_ & 0x3)) \
- LOC = text_seg [(_addr_ - TEXT_BOT) >> 2]; \
- else if (_addr_ >= K_TEXT_BOT && _addr_ < k_text_top && !(_addr_ & 0x3))\
- LOC = k_text_seg [(_addr_ - K_TEXT_BOT) >> 2]; \
- else LOC = funny_text_read (_addr_);}
-
-
- #define READ_MEM_BYTE(LOC, ADDR) \
- {register mem_addr _addr_ = (mem_addr) (ADDR); \
- if (_addr_ >= DATA_BOT && _addr_ < data_top) \
- LOC = data_seg_b [_addr_ - DATA_BOT]; \
- else if (_addr_ >= stack_bot && _addr_ < STACK_TOP) \
- LOC = stack_seg_b [_addr_ - stack_bot]; \
- else if (_addr_ >= K_DATA_BOT && _addr_ < k_data_top) \
- LOC = k_data_seg_b [_addr_ - K_DATA_BOT]; \
- else \
- LOC = bad_mem_read (_addr_, 0, (mem_word *) &LOC);}
-
-
- #define READ_MEM_HALF(LOC, ADDR) \
- {register mem_addr _addr_ = (mem_addr) (ADDR); \
- if (_addr_ >= DATA_BOT && _addr_ < data_top && !(_addr_ & 0x1)) \
- LOC = data_seg_h [(_addr_ - DATA_BOT) >> 1]; \
- else if (_addr_ >= stack_bot && _addr_ < STACK_TOP && !(_addr_ & 0x1)) \
- LOC = stack_seg_h [(_addr_ - stack_bot) >> 1]; \
- else if (_addr_ >= K_DATA_BOT && _addr_ < k_data_top && !(_addr_ & 0x1))\
- LOC = k_data_seg_h [(_addr_ - K_DATA_BOT) >> 1]; \
- else \
- LOC = bad_mem_read (_addr_, 0x1, (mem_word *) &LOC);}
-
-
- #define READ_MEM_WORD(LOC, ADDR) \
- {register mem_addr _addr_ = (mem_addr) (ADDR); \
- if (_addr_ >= DATA_BOT && _addr_ < data_top && !(_addr_ & 0x3)) \
- LOC = data_seg [(_addr_ - DATA_BOT) >> 2]; \
- else if (_addr_ >= stack_bot && _addr_ < STACK_TOP && !(_addr_ & 0x3)) \
- LOC = stack_seg [(_addr_ - stack_bot) >> 2]; \
- else if (_addr_ >= K_DATA_BOT && _addr_ < k_data_top && !(_addr_ & 0x3))\
- LOC = k_data_seg [(_addr_ - K_DATA_BOT) >> 2]; \
- else \
- LOC = bad_mem_read (_addr_, 0x3, (mem_word *) &LOC);}
-
-
- extern void make_memory(long text_size,long data_size,long data_limit,
- long stack_size,long stack_limit,long k_text_size,long k_data_size,
- long k_data_limit);
- extern void expand_data(long addl_bytes);
- extern void expand_stack(long addl_bytes);
- extern void expand_k_data(long addl_bytes);
- extern instruction *funny_text_read(mem_addr addr);
- extern void funny_text_write(mem_addr addr, instruction *inst);
- extern mem_word bad_mem_read(mem_addr addr,int mask,mem_word *dest);
- extern void bad_mem_write(mem_addr addr,mem_word value,int mask);
- extern void print_mem(mem_addr addr);
-
- #undef EXTERN
-